package com.study.config;

import com.study.shiro.AuthRealm;
import com.study.shiro.CustomCredentialsMatcher;
import com.study.shiro.MyAccessControlFilter;
import com.study.shiro.ShiroSessionFactory;
import net.sf.ehcache.CacheManager;
import org.apache.commons.collections.map.HashedMap;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.apache.shiro.mgt.SecurityManager;
import org.springframework.context.annotation.DependsOn;

import javax.servlet.Filter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/*********************************************************
 * @Author ONE_LLX
 * @Description shiro 配置管理器
 * @Date 15:35 2019/10/11
 * @Class ShiroConfig
 * @Version v1.0
 * 安全管理器
 * 配置Realm域
 * 密码比较器 -->
 * 代理如何生成？ 用工厂来生成Shiro的相关过滤器
 * 配置缓存：ehcache缓存
 *
 *********************************************************/
@Configuration
public class ShiroConfig {

    public static final String SESSIONID="cookiename";

    public static final Long SESSIONTIMEOUT=72000L;
    /**
     * ehcache 缓存
     * @return
     */
    @Bean
    public EhCacheManager ehCacheManager() {
        CacheManager cacheManager = CacheManager.getCacheManager("shiroCache");
        if(cacheManager == null){
            cacheManager = CacheManager.create();
        }
        EhCacheManager em = new EhCacheManager();
        //将ehcacheManager转换成shiro包装后的ehcacheManager对象
        em.setCacheManager(cacheManager);
        //em.setCacheManagerConfigFile("classpath:ehcache.xml");
        return em;
    }

    /**
     * 会话Cookie模板会话Cookie模板
     * @return
     */
    @Bean
    public SimpleCookie cookie(){
        SimpleCookie cookie=new SimpleCookie();
        cookie.setName(SESSIONID);//设置cookie名称
        cookie.setHttpOnly(true);//允许只读
        cookie.setMaxAge(-1);//maxAge=-1表示浏览器关闭时失效此Cookie
        return cookie;
    }

    /**
     * shiroFactory
     * @return
     */
    @Bean
    public ShiroSessionFactory sessionFactory(){
        ShiroSessionFactory sessionFactory=new ShiroSessionFactory();
        return sessionFactory;
    }
    @Bean
    public DefaultWebSessionManager sessionManager(){
        DefaultWebSessionManager sessionManager=new DefaultWebSessionManager();
        sessionManager.setGlobalSessionTimeout(SESSIONTIMEOUT);//
        sessionManager.setSessionValidationSchedulerEnabled(true);//开启检测
        sessionManager.setDeleteInvalidSessions(true);//删除失效的session
        sessionManager.setSessionIdCookie(cookie());
        sessionManager.setSessionFactory(sessionFactory());
//        sessionManager.setSessionValidationScheduler(scheduler());
        return sessionManager;
    }

    /**
     * 会话验证调度器，每隔一段时间清理失效的用户session
     * @return
     */
    @Bean
    public ExecutorServiceSessionValidationScheduler scheduler(){
        ExecutorServiceSessionValidationScheduler scheduler=new ExecutorServiceSessionValidationScheduler();
        scheduler.setInterval(SESSIONTIMEOUT);
        DefaultWebSessionManager sessionManager = sessionManager();
        scheduler.setSessionManager(sessionManager);
        return scheduler;
    }

    /**
     * 密码比较器
     */
    @Bean
    public SimpleCredentialsMatcher customCredentialsMatcher() {
        CustomCredentialsMatcher matcher=new CustomCredentialsMatcher();
        return matcher;
    }

    /**
     * 验证方式
     * @return
     */
    @Bean
    public AuthRealm myShiroRealm() {
        AuthRealm myShiroRealm = new AuthRealm();
        //将加密方式绑定到自定义的realm
        myShiroRealm.setCredentialsMatcher(customCredentialsMatcher());
        return myShiroRealm;
    }

    /**
     * 安全管理器
     * @return
     */
    @Bean
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setSessionManager(sessionManager());//session管理器
        securityManager.setCacheManager(ehCacheManager());//缓存管理器
        List realms=new ArrayList();
        realms.add(myShiroRealm());//可以配置多个realm
        securityManager.setRealms(realms);
        return securityManager;
    }

    //Filter工厂，设置对应的过滤条件和跳转条件
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // 必须设置 SecurityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        MyAccessControlFilter filter=new MyAccessControlFilter();
        Map<String, Filter> filterMap=new HashedMap();
        filterMap.put("myAccessControlFilter",filter);
        shiroFilterFactoryBean.setFilters(filterMap);
        // 拦截器
        Map<String,String> map = new HashMap<String, String>();
        map.put("/manager/login","anon");
        map.put("/**","anon");
        map.put("/*.*","anon");
        map.put("/**","myAccessControlFilter");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }

    /**
     *
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor( ) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
        return authorizationAttributeSourceAdvisor;
    }


    @Bean(name = "postProcessor")
    public LifecycleBeanPostProcessor postProcessor(){
        LifecycleBeanPostProcessor postProcessor=new LifecycleBeanPostProcessor();
        return postProcessor;
    }

    @DependsOn(value = {"postProcessor"})
    @Bean
    public DefaultAdvisorAutoProxyCreator proxyCreator(){
        DefaultAdvisorAutoProxyCreator proxyCreator=new DefaultAdvisorAutoProxyCreator();
        proxyCreator.setProxyTargetClass(true);
        return proxyCreator;
    }

}
